package de.g18.it0a.jlaser.gui.view;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;

import javax.swing.JPanel;

import de.g18.it0a.jlaser.domain.Position;
import de.g18.it0a.jlaser.domain.Room;

public class RoomEditorPanel extends JPanel {

    private static final long serialVersionUID = 1L;

    private Room room;
    private boolean calculating;
    private long startTime;


    public RoomEditorPanel() {
        setPreferredSize(new Dimension(800, 500));
        setMinimumSize(getPreferredSize());
    }

    public Room getRoom() {
        return room;
    }

    public void setRoom(Room aRoom) {
        room = aRoom;
        repaint();
    }

    public boolean isCalculating() {
        return calculating;
    }

    public void setCalculating(boolean aIsCalculating) {
        calculating = aIsCalculating;
        if (isCalculating()) {
            startTime = System.currentTimeMillis();
        } else {
            System.out.println("Benötigte Zeit: " + (System.currentTimeMillis() - startTime) / 1000.0);
        }
        repaint();
    }

    @Override
    protected void paintComponent(Graphics aGraphics) {
        Graphics2D paintGraphics = (Graphics2D) aGraphics.create();
        try {
            paintRoom(paintGraphics);
        } finally {
            paintGraphics.dispose();
        }
    }

    private void paintRoom(Graphics2D aGraphics) {
        paintBackground(aGraphics);
        if (getRoom() == null) {
            paintCreateOrLoadRoomText(aGraphics);
            return;
        }
        SolutionView view = new SolutionView(getRoom());
        BufferedImage renderedRoom = view.render();
        if (renderedRoom.getWidth() > getWidth() || renderedRoom.getHeight() > getHeight()) {
            renderedRoom = scaleImageToFitInPane(renderedRoom);
        }

        Position centerPosition = getCenterPosition(renderedRoom);
        AffineTransform transform = new AffineTransform();
        transform.setToTranslation(centerPosition.getX(), centerPosition.getY());
        aGraphics.drawImage(renderedRoom, transform, null);
        if (isCalculating()) {
            paintCalculatingRoomText(aGraphics);
        }
    }

    private BufferedImage scaleImageToFitInPane(BufferedImage aImage) {
        double scaledHeight = getHeight() * 1.0f / aImage.getHeight();
        double scaledWidth = getWidth() * 1.0f / aImage.getWidth();
        BufferedImage scaledImage = new BufferedImage((int) (scaledWidth * aImage.getWidth()),
                                                      (int) (scaledHeight * aImage.getHeight()),
                                                      BufferedImage.TYPE_INT_ARGB);
        Graphics2D graphics2D = scaledImage.createGraphics();
        AffineTransform transformation = AffineTransform.getScaleInstance(scaledWidth, scaledHeight);
        graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
        graphics2D.drawImage(aImage, transformation, null);
        graphics2D.dispose();
        return scaledImage;
    }

    private void paintBackground(Graphics2D aGraphics) {
        aGraphics.setColor(Color.BLACK);
        aGraphics.fillRect(0, 0, getWidth(), getHeight());
    }

    private void paintCalculatingRoomText(Graphics2D aGraphics) {
        aGraphics.setColor(Color.GRAY);
        aGraphics.setFont(getFont().deriveFont(Font.BOLD));
        FontMetrics metrics = aGraphics.getFontMetrics();

        String text = "Spiegelpositionen werden berechnet, bitte haben Sie einen Moment gedult...";
        int width = metrics.stringWidth(text);
        aGraphics.drawString(text, getWidth() / 2 - width / 2, 20);
    }

    private void paintCreateOrLoadRoomText(Graphics2D aGraphics) {
        aGraphics.setColor(Color.GRAY);
        aGraphics.setFont(getFont().deriveFont(Font.BOLD));
        FontMetrics metrics = aGraphics.getFontMetrics();

        String text = "Bitte erstellen/laden Sie zuerst einen Raum, um diesen zu bearbeiten.";
        int width = metrics.stringWidth(text);
        aGraphics.drawString(text, getWidth() / 2 - width / 2, 50);
    }

    private Position getCenterPosition(BufferedImage aImage) {
        return new Position((getWidth() - aImage.getWidth()) / 2,
                            (getHeight() - aImage.getHeight()) / 2);
    }
}
